//package com.tianji.aigc.service.impl;
//
//import cn.hutool.core.collection.CollUtil;
//import cn.hutool.core.date.DateUtil;
//import cn.hutool.core.map.MapUtil;
//import cn.hutool.core.stream.StreamUtil;
//import cn.hutool.core.util.IdUtil;
//import cn.hutool.core.util.ReflectUtil;
//import cn.hutool.core.util.StrUtil;
//import com.tianji.aigc.config.SystemPromptConfig;
//import com.tianji.aigc.config.ToolResultHolder;
//import com.tianji.aigc.constants.Constant;
//import com.tianji.aigc.domain.vo.ChatEventVO;
//import com.tianji.aigc.domain.vo.MessageVO;
//import com.tianji.aigc.enums.ChatEventTypeEnum;
//import com.tianji.aigc.enums.MessageTypeEnum;
//import com.tianji.aigc.service.ChatService;
//
//import com.tianji.aigc.service.ChatSessionService;
//import com.tianji.common.utils.UserContext;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.ai.chat.client.ChatClient;
//import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
//import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
//import org.springframework.ai.chat.memory.ChatMemory;
//import org.springframework.ai.chat.messages.AssistantMessage;
//import org.springframework.ai.chat.messages.Message;
//import org.springframework.ai.chat.messages.MessageType;
//import org.springframework.ai.chat.metadata.ChatResponseMetadata;
//import org.springframework.ai.vectorstore.SearchRequest;
//import org.springframework.ai.vectorstore.VectorStore;
//import org.springframework.stereotype.Service;
//import reactor.core.publisher.Flux;
//
//import java.util.List;
//import java.util.Map;
//import java.util.Optional;
//import java.util.concurrent.ConcurrentHashMap;
//
//@Slf4j
////@Service
//@RequiredArgsConstructor
//public class ChatServiceImpl implements ChatService {
//
//    private final ChatClient dashScopeChatClient;
//    private final SystemPromptConfig systemPromptConfig;
//
//    // 存储大模型的生成状态，这里采用ConcurrentHashMap是确保线程安全
//    // 目前的版本暂时用Map实现，如果考虑分布式环境的话，可以考虑用redis来实现
//    private static final Map<String, Boolean> GENERATE_STATUS = new ConcurrentHashMap<>();
//    private final ChatMemory chatMemory;
//
//    // 输出结束的标记
//    private static final ChatEventVO STOP_EVENT = ChatEventVO.builder().eventType(ChatEventTypeEnum.STOP.getValue()).build();
//
//    private final VectorStore vectorStore;
//
//    private final ChatSessionService chatSessionService;
//
//
//    @Override
//    public Flux<ChatEventVO> chat(String question, String sessionId) {
//        // 获取对话id
//        var conversationId = ChatService.getConversationId(sessionId);
//        // 大模型输出内容的缓存器，用于在输出中断后的数据存储
//        StringBuilder outputBuilder = new StringBuilder();
//        // 生成请求id
//        var requestId = IdUtil.fastSimpleUUID();
//        // 获取用户id
//        var userId = UserContext.getUser();
//
//        //更新会话时间
//        this.chatSessionService.update(sessionId, question, userId);
//
//        return this.dashScopeChatClient.prompt()
//                .system(promptSystem -> promptSystem
//                        .text(this.systemPromptConfig.getChatSystemMessage().get()) // 设置系统提示语
//                        .param("now", DateUtil.now()) // 设置当前时间的参数
//                )
//                .advisors(advisor -> advisor
//                        // 设置RAG查询，因为数据量不大，所以直接全部查询
//                        .advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.builder().query("").topK(999).build()))
//                        .param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, conversationId)
//                )
//                .toolContext(MapUtil.<String, Object>builder() // 设置tool列表
//                        .put(Constant.REQUEST_ID, requestId) // 设置请求id参数
//                        .put(Constant.USER_ID, userId) // 设置用户id参数
//                        .build()
//                )
//                .user(question)
//                .stream()
//                .chatResponse()
//                .doFirst(() -> { //输出开始，标记正在输出
//                    GENERATE_STATUS.put(sessionId, true);
//                })
//                .doOnComplete(() -> { //输出结束，清除标记
//                    GENERATE_STATUS.remove(sessionId);
//                })
//                .doOnError(throwable -> GENERATE_STATUS.remove(sessionId)) // 错误时清除标记
//                .doOnCancel(() -> {
//                    // 当输出被取消时，保存输出的内容到历史记录中
//                    this.saveStopHistoryRecord(conversationId, outputBuilder.toString());
//                })
//                // 输出过程中，判断是否正在输出，如果正在输出，则继续输出，否则结束输出
//                .takeWhile(s -> Optional.ofNullable(GENERATE_STATUS.get(sessionId)).orElse(false))
//                .map(chatResponse -> {
//                    // 对于响应结果进行处理，如果是最后一条数据，就把此次消息id放到内存中
//                    // 主要用于存储消息数据到 redis中，可以根据消息di获取的请求id，再通过请求id就可以获取到参数列表了
//                    // 从而解决，在历史聊天记录中没有外参数的问题
//                    var finishReason = chatResponse.getResult().getMetadata().getFinishReason();
//                    if (StrUtil.equals(Constant.STOP, finishReason)) {
//                        var messageId = ((ChatResponseMetadata) ReflectUtil.getFieldValue(chatResponse, Constant.Chats.CHAT_RESPONSE_METADATA)).getId();
//                        ToolResultHolder.put(messageId, Constant.REQUEST_ID, requestId);
//                    }
//                    // 获取大模型的输出的内容
//                    String text = chatResponse.getResult().getOutput().getText();
//                    // 追加到输出内容中
//                    outputBuilder.append(text);
//                    // 封装响应对象
//                    return ChatEventVO.builder()
//                            .eventData(text)
//                            .eventType(ChatEventTypeEnum.DATA.getValue())
//                            .build();
//                })
//                .concatWith(Flux.defer(() -> {
//                    // 通过请求id获取到参数列表，如果不为空，就将其追加到返回结果中
//                    var map = ToolResultHolder.get(requestId);
//                    if (CollUtil.isNotEmpty(map)) {
//                        ToolResultHolder.remove(requestId); // 清除参数列表
//
//                        // 响应给前端的参数数据
//                        ChatEventVO chatEventVO = ChatEventVO.builder()
//                                .eventData(map)
//                                .eventType(ChatEventTypeEnum.PARAM.getValue())
//                                .build();
//                        return Flux.just(chatEventVO, STOP_EVENT);
//                    }
//                    return Flux.just(STOP_EVENT);
//                }));
//    }
//    /**
//     * 保存停止输出的记录
//     *
//     * @param conversationId 会话id
//     * @param content        大模型输出的内容
//     */
//    private void saveStopHistoryRecord(String conversationId, String content) {
//        this.chatMemory.add(conversationId, new AssistantMessage(content));
//    }
//
//    @Override
//    public void stop(String sessionId) {
//        // 停止大模型输出.移除标记
//        GENERATE_STATUS.remove(sessionId);
//    }
//
//
//
//
//
//}
